package com.swak.reactivex.future;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

public class PromiseFuture extends CompletableFuture<Void> {

	public static <F extends Future<Void>> PromiseFuture from(F future) {
		if (future.isDone()) {
			if (!future.isSuccess()) {
				return PromiseFuture.error(future.cause());
			}
			return PromiseFuture.success();
		}
		return new ImmediateFutureMono<>(future);
	}

	public static PromiseFuture error(Throwable error) {
		PromiseFuture future = new PromiseFuture();
		future.completeExceptionally(error);
		return future;
	}

	public static PromiseFuture success() {
		PromiseFuture future = new PromiseFuture();
		future.complete(null);
		return future;
	}

	public static CompletableFuture<Void> when(PromiseFuture[] futures) {
		return CompletableFuture.allOf(futures);
	}

	final static class ImmediateFutureMono<F extends Future<Void>> extends PromiseFuture
			implements GenericFutureListener<F> {

		final F future;

		ImmediateFutureMono(F future) {
			this.future = Objects.requireNonNull(future, "future");
			this.future.addListener(this);
		}

		@Override
		public void operationComplete(F future) throws Exception {
			if (!future.isSuccess()) {
				this.completeExceptionally(future.cause());
			} else {
				this.complete(null);
			}
		}
	}
}
